package com.snoob.lixing.aop;

import com.snoob.lixing.util.LoggerUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;

/**
 * Created with IntelliJ IDEA
 * User: lixing
 * Date: 2018/11/25 17:17
 * <p>
 * 通过AOP对控制器的异常进行拦截并写入日志
 */
@Aspect
@Component
public class ControllerExceptionAspect {

    /**
     * 切点,拦截所有的控制层
     */
    @Pointcut("execution(public * com.snoob.lixing.controller.*.*(..))")
    public void exceptionPointCut() {
    }

    /**
     * 前置通知： 权限校验等等
     */
    @Before("exceptionPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 当前请求的url
        String requestUrl = request.getRequestURI();

        // 如果是登陆操作,则将获取ip放入request对象
        if (requestUrl.contains("user/login")) {
            String requestIp = request.getRemoteAddr();
            request.setAttribute("ip", requestIp);
        }
    }

    /**
     * 异常通知： 全局异常日志记录
     */
    @AfterThrowing(pointcut = "exceptionPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String requestUrl = request.getRequestURI(); // 当前请求的url
        String requestType = request.getMethod(); // 请求类型,GET\POST
        //Object[] requestArgs = joinPoint.getArgs(); // 请求参数
        String controllerMethodName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(); // 控制器方法名称
        String errorMsg = e.getMessage(); // 异常信息

        LoggerUtil.debug("=========================AOP捕获控制器异常【START】");
        LoggerUtil.debug(MessageFormat.format("请求链接: {0}", requestUrl));
        LoggerUtil.debug(MessageFormat.format("请求方法类型:{0}", requestType));
        LoggerUtil.debug(MessageFormat.format("控制器方法名:{0}", controllerMethodName));
        LoggerUtil.debug(MessageFormat.format("异常信息:{0}", errorMsg));
        LoggerUtil.debug("=========================AOP捕获控制器异常【END】");
    }
}
